package com.reservation.service;

import com.reservation.dto.CreateReservationRequest;
import com.reservation.dto.ReservationDTO;
import com.reservation.entity.Product;
import com.reservation.entity.Reservation;
import com.reservation.enums.ReservationStatus;
import com.reservation.mapper.ReservationMapper;
import com.reservation.mapper.ProductMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 预定服务类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ReservationService {

    private final ReservationMapper reservationMapper;
    private final ProductMapper productMapper;
    private final ProductService productService;

    /**
     * 创建预定
     */
    @Transactional
    public ReservationDTO createReservation(CreateReservationRequest request) {
        log.info("创建预定: {}", request);
        
        // 验证商品存在且有足够库存
        Product product = productMapper.selectByIdAndActive(request.getProductId());
        if (product == null) {
            throw new RuntimeException("商品不存在或已下架");
        }
        
        if (!product.hasEnoughStock(request.getQuantity())) {
            throw new RuntimeException("库存不足，当前库存：" + product.getStock());
        }
        
        // 减少库存
        productService.decreaseStock(request.getProductId(), request.getQuantity());
        
        // 创建预定记录
        Reservation reservation = new Reservation();
        reservation.setUserId(request.getUserId());
        reservation.setProductId(request.getProductId());
        reservation.setTotalAmount(product.getPrice().multiply(BigDecimal.valueOf(request.getQuantity())));
        reservation.setStatus("PENDING");
        reservation.setContactName(request.getContactName());
        reservation.setContactPhone(request.getContactPhone());
        reservation.setRemark(request.getNotes());
        reservation.setOrderNumber(generateOrderNumber());
        reservation.setPaymentStatus("UNPAID");

        // 设置预订日期和时间（这里需要根据实际业务逻辑设置）
        reservation.setReservationDate(LocalDate.now().plusDays(1)); // 默认明天
        reservation.setReservationTime(LocalTime.of(10, 0)); // 默认上午10点
        reservation.setPersonCount(request.getQuantity()); // 使用数量作为人数

        reservationMapper.insert(reservation);
        log.info("预定创建成功: reservationId={}", reservation.getId());

        return convertToDTO(reservation);
    }

    /**
     * 确认预定
     */
    @Transactional
    public ReservationDTO confirmReservation(Long reservationId) {
        log.info("确认预定: reservationId={}", reservationId);
        
        Reservation reservation = reservationMapper.selectById(reservationId);
        if (reservation == null) {
            throw new RuntimeException("预定记录不存在");
        }

        reservation.setStatus("CONFIRMED");
        reservationMapper.update(reservation);
        log.info("预定确认成功: reservationId={}", reservationId);

        return convertToDTO(reservation);
    }

    /**
     * 取消预定
     */
    @Transactional
    public ReservationDTO cancelReservation(Long reservationId) {
        log.info("取消预定: reservationId={}", reservationId);
        
        Reservation reservation = reservationMapper.selectById(reservationId);
        if (reservation == null) {
            throw new RuntimeException("预定记录不存在");
        }

        // 恢复库存
        if (!"CANCELLED".equals(reservation.getStatus())) {
            productService.increaseStock(reservation.getProductId(), reservation.getPersonCount());
        }

        reservation.setStatus("CANCELLED");
        reservationMapper.update(reservation);
        log.info("预定取消成功: reservationId={}", reservationId);

        return convertToDTO(reservation);
    }

    /**
     * 完成预定
     */
    @Transactional
    public ReservationDTO completeReservation(Long reservationId) {
        log.info("完成预定: reservationId={}", reservationId);
        
        Reservation reservation = reservationMapper.selectById(reservationId);
        if (reservation == null) {
            throw new RuntimeException("预定记录不存在");
        }

        reservation.setStatus("COMPLETED");
        reservationMapper.update(reservation);
        log.info("预定完成: reservationId={}", reservationId);

        return convertToDTO(reservation);
    }

    /**
     * 获取用户的预定记录
     */
    public List<ReservationDTO> getUserReservations(Long userId) {
        log.info("获取用户预定记录: userId={}", userId);
        List<Reservation> reservations = reservationMapper.selectByUserId(userId);
        return reservations.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 根据状态获取用户的预定记录
     */
    public List<ReservationDTO> getUserReservationsByStatus(Long userId, ReservationStatus status) {
        log.info("根据状态获取用户预定记录: userId={}, status={}", userId, status);
        List<Reservation> reservations = reservationMapper.selectByUserIdAndStatus(userId, status.getCode());
        return reservations.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 根据ID获取预定记录
     */
    public Optional<ReservationDTO> getReservationById(Long reservationId) {
        log.info("根据ID获取预定记录: reservationId={}", reservationId);
        Reservation reservation = reservationMapper.selectById(reservationId);
        return Optional.ofNullable(reservation).map(this::convertToDTO);
    }

    /**
     * 获取所有预定记录
     */
    public List<ReservationDTO> getAllReservations() {
        log.info("获取所有预定记录");
        List<Reservation> reservations = reservationMapper.selectAll();
        return reservations.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }

    /**
     * 统计用户预定数量
     */
    public Long countUserReservations(Long userId) {
        return reservationMapper.countByUserId(userId);
    }

    /**
     * 统计指定状态的预定数量
     */
    public Long countReservationsByStatus(ReservationStatus status) {
        return reservationMapper.countByStatus(status.getCode());
    }

    /**
     * 清理超时未确认的预定
     */
    @Transactional
    public void cleanupExpiredReservations(int expireHours) {
        log.info("清理超时未确认的预定: expireHours={}", expireHours);
        LocalDateTime expireTime = LocalDateTime.now().minusHours(expireHours);
        List<Reservation> expiredReservations = reservationMapper.selectExpiredPendingReservations(expireTime);

        for (Reservation reservation : expiredReservations) {
            // 恢复库存
            productService.increaseStock(reservation.getProductId(), reservation.getPersonCount());
            // 取消预定
            reservation.setStatus("CANCELLED");
            reservationMapper.update(reservation);
            log.info("自动取消超时预定: reservationId={}", reservation.getId());
        }
    }

    /**
     * 转换为DTO
     */
    private ReservationDTO convertToDTO(Reservation reservation) {
        ReservationDTO dto = new ReservationDTO();
        dto.setId(reservation.getId());
        dto.setUserId(reservation.getUserId());
        dto.setProductId(reservation.getProductId());

        // 获取产品信息
        if (reservation.getProductId() != null) {
            Product product = productMapper.selectById(reservation.getProductId());
            if (product != null) {
                dto.setProductName(product.getName());
                dto.setProductPrice(product.getPrice());
                dto.setProductImage(product.getImage());
            }
        }

        dto.setQuantity(reservation.getPersonCount()); // 使用personCount作为quantity
        dto.setTotalAmount(reservation.getTotalAmount());
        dto.setStatus(ReservationStatus.valueOf(reservation.getStatus().toUpperCase()));
        dto.setContactName(reservation.getContactName());
        dto.setContactPhone(reservation.getContactPhone());
        dto.setContactAddress(""); // 当前Reservation实体中没有地址字段
        dto.setNotes(reservation.getRemark());
        dto.setCreatedAt(reservation.getCreatedAt());
        dto.setUpdatedAt(reservation.getUpdatedAt());
        return dto;
    }

    /**
     * 生成订单号
     */
    private String generateOrderNumber() {
        return "R" + System.currentTimeMillis();
    }
}
